'''
Created on 2018年1月21日

@author: heguofeng

pip install xlrd
'''
import unittest
from tkinter import *
from tkinter.ttk import *
from secure_book import SecureRecord,SecureBook
from tkinter.filedialog import askopenfilename,asksaveasfilename
from tkinter.messagebox import showinfo,askyesnocancel
from datetime import date
from tkinter.simpledialog import askstring
from xlrd import open_workbook
from xlwt import Workbook




Field = ['tag','name','uri','username','password','password1','ref','date']
FieldName = {'tag':'标记','name':'名称','uri':'uri','username':'用户名',\
             'password':'密码','password1':'再输密码','ref':'备注','date':'日期'}

class PasswordWidget(Toplevel):
    def __init__(self,title,pwcallback):
        '''password is a stringvar
        '''
        Toplevel.__init__(self)
        self.title(title)
        self.focus()
        self.geometry("330x100+400+300")
        self.pwcallback = pwcallback
        self.value = StringVar()
        self.createWidgets()

        #self.grid(row=0,column=0)
        
    def createWidgets(self):
        self.label = Label(self, compound="left" , anchor='w',text="密码：")
        self.entry = Entry(self, width=40, textvariable=self.value)
        self.label.grid(row=1,column=0)
        self.entry.grid(row=1,column=1)
        self.okButton = Button(self, text="OK", command=self.saveQuit)     
        self.cancelButton = Button(self, text="Cancel", command=self.cancel)
        self.okButton.grid(row=2,column=0)
        self.cancelButton.grid(row=2,column=1)
        pass
    
    def saveQuit(self):
        if self.pwcallback(self.value.get()):
            self.destroy()
        else:
            showinfo(title="error",message="密码错误！")
            self.focus()
        pass
    
    def cancel(self):
        self.destroy()
        pass
    
    def callback(self):
        self.destroy()

class SecureRecordWidget(Frame):
    
    def __init__(self,master=None,secure_record=None,iid="",secure_book_widget=None):
        
        super().__init__(master)
        master.title("记录")
        master.focus()
        master.geometry("330x250+400+300")
        self.textvar = {}
        for item in Field:
            self.textvar[item]=StringVar()
        if secure_record!=None:
            values = secure_record.get()
            values['password1']=values['password']
            for item in Field:
                self.textvar[item].set(values[item])
        self.createWidgets()
        self.iid = iid
        self.secureBookWidget =  secure_book_widget
        
    def createWidgets(self):
        self.labels = {}
        self.entrys = {}
        rowcount = 1
        self.titleLabel = Label(self, compound="left" , anchor='w',text="Records")
        self.titleLabel.grid(row=0,column=3)
        for item in Field:
            self.labels[item] = Label(self, compound="left" , anchor='w',text=FieldName[item])
            self.entrys[item] = Entry(self, width=40, textvariable=self.textvar[item])
            self.labels[item].grid(row=rowcount,column=1)
            self.entrys[item].grid(row=rowcount,column=2,columnspan=3)
            rowcount += 1  
            if item.find('password')>=0:
                #self.entrys[item].config(show='*')
                pass

        self.entrys["date"].config(state='disabled')
        
        self.okButton = Button(self, text="OK", command=self.saveQuit)     
        self.cancelButton = Button(self, text="Cancel", command=self.cancel)
        self.okButton.grid(row=rowcount,column=2)
        self.cancelButton.grid(row=rowcount,column=4)
        
    def samePass(self):
        if self.textvar["password1"].get() == self.textvar['password'].get():
            return True
        else:
            showinfo(title="error",message="password not same!")
            self.focus()
            return False 
        
    def saveQuit(self):
        if not self.samePass():
            return
        record = {}
        for field in SecureRecord.getFields():
            record[field] =  self.entrys[field].get()
        record["date"] = date.today()
        if self.secureBookWidget!=None:
            self.secureBookWidget.saveRecord(self.iid,record)
        self.master.destroy()  
        pass
    
    def cancel(self):
        self.master.destroy()     

class SecureBookWidgets(Frame):
    def __init__(self,master=None,config={}):
        super().__init__(master)
        self.secureBookName = StringVar()
        self.tempValue = StringVar()
        self.iidRecord={}
        self.createWidgets()
        self.bookTreeview.bind("<Double-Button-1>", self.editRecord)
        self.bookTreeview.bind("<Button-3>", self.popupMenu)

        self.secureBook = None

        pass
    
    def createWidgets(self):
        self.bookLabel = Label(self, compound="left" , anchor='w',text="密码本,请使用右键开启更多功能")
#         self.bookEntry = Entry(self, width=40, textvariable=self.secureBookName)
        self.bookOpenButton = Button(self, text="打开", command=self.open_command)
        self.bookSaveButton = Button(self, text="保存", command=self.save)
        self.bookNewBookButton = Button(self, text="新建", command=self.newBook)
        self.bookNewRecordButton = Button(self, text="新建记录", command=self.newRecord)
        
        fields  = SecureRecord.getFields()
        displayfields= fields[:].remove("password")
        self.bookTreeview = Treeview(self, columns=tuple(fields), \
                                displaycolumns=displayfields, \
                                height=16, show='tree headings')
#         self.bookTreeview = Treeview(self, columns=tuple(SecureBook.getFields())"Tag", "Name", "URI", "UserName", "Password", "Memo","Date"), \
#                                 displaycolumns=["Tag", "Name", "URI", "UserName",  "Memo","Date"], \
#                                 height=16, show='tree headings')
        self.bookTreeview.heading('#0', command=self.sortClear)
        fielddict = SecureRecord.getFieldDict()
        for field in fields:
            self.bookTreeview.heading(field,text=fielddict[field])
            self.bookTreeview.column(field, width=80)
        self.bookTreeview.column('#0', width=20)

#         self.bookTreeview.column('Tag', width=80)
#         self.bookTreeview.column('Name', width=80)
#         self.bookTreeview.column('URI', width=260)
#         self.bookTreeview.column('UserName', width=80)
#         self.bookTreeview.column('Date', width=80)
#         self.bookTreeview.column('Password', width=80)
#         self.bookTreeview.column('#0', width=20)
        self.bookScrollbar = Scrollbar(self, orient=VERTICAL)

        self.bookLabel.grid(row=0, column=0, sticky= W)
#         self.bookEntry.grid(row=0, column=1, columnspan=3, sticky=E + W)
        self.bookOpenButton.grid(row=0, column=6, sticky=E + W)
        self.bookSaveButton.grid(row=0, column=7, sticky=E + W)
        self.bookNewBookButton.grid(row=0, column=8, sticky=E + W)
        self.bookNewRecordButton.grid(row=0, column=9, sticky=E + W)
        self.bookTreeview.grid(row=1, column=0, rowspan=16, columnspan=10, sticky=W + E + N + S)
        self.bookScrollbar.grid(row=1, column=9, rowspan=16, sticky=N + S + E)
        
        self.bookLabel.rowconfigure(0, weight=1)
        self.bookLabel.rowconfigure(0, weight=1)
        
        self.bookScrollbar.configure(command=self.bookTreeview.yview)
        self.bookTreeview.configure(yscrollcommand=self.bookScrollbar.set)
        
#         self.tagFilterLabel = Label(self, text="Tag:")
#         self.tagFilterLabel.grid(row=17, column=0)
#         self.tagFilterCombobox = Combobox(self , \
#                                              values=("home","work","All"), \
#                                              width=8)
#         self.tagFilterCombobox.grid(row=17, column=1)
#         self.tagFilterCombobox.set("All")
        self.statusLabel = Label(self, text="", anchor='w',wraplength=500)
        self.statusLabel.grid(row=18, column=0, columnspan=10, sticky=W + E)

        self.popmenu = Menu(self, tearoff=0)
        self.popmenu.add_command(label="打开本地密码本",command=self.open_command)
        self.popmenu.add_command(label="打开网络密码本",command = self.open_net_command )
        self.popmenu.add_command(label="保存", command=self.save)
        self.popmenu.add_command(label="新建", command=self.newBook)
        self.popmenu.add_command(label="另存", command=self.save_as)  
        self.popmenu.add_command(label="修改密码", command =self.change_key)         
        self.popmenu.add_separator()
        self.popmenu.add_command(label="插入记录", command=self.newRecord)
        self.popmenu.add_command(label="删除记录", command=self.delete_record)
        self.popmenu.add_command(label="取消选择", command=self.removeSelected)
        self.popmenu.add_command(label="导出记录", command=self.export_csv)
        self.popmenu.add_command(label="导入记录", command=self.load_csv)
        
        self.popupCCPMenu = Menu(self, tearoff=0)
        self.popupCCPMenu.add_command(label="copy", command=self.popupCopy)
        self.popupCCPMenu.add_command(label="paste", command=self.popupPaste)
        
        self.bookEditEntry = Entry(self.bookTreeview, width=40, textvariable=self.tempValue)
        self.bookEditEntry.grid_bbox(1,25,500,40)

    def popupMenu(self, event):
        self.popmenu.post(event.x_root, event.y_root)  
        
    def change_key(self):
        key = askstring("请输入密码","密码")
        if key:
            self.secureBook.setkey(key)
        pass
    
    def editRecord(self,event):
        srw = SecureRecordWidget(Toplevel(),self.iidRecord[self.bookTreeview.identify_row(event.y)],self.bookTreeview.identify_row(event.y),self)
        srw.grid(row=1,column=1)
        
    def saveRecord(self,iid,record):
        if iid=="":
            srecord = SecureRecord(record=record)
            myIid = self.insertItem("", srecord)
            self.secureBook.append(srecord)
            self.iidRecord[myIid] =  srecord
        else:
            self.iidRecord[iid].set(record)
            self.updateItem(iid, record)
        pass
            
    def save(self):
        if self.secureBook.url:
            if not self.secureBook.key:
                self.chang_key()
            self.secureBook.save()
            self.statusLabel.config(text="Saved in %s"% self.secureBook.url)
        else:
            self.save_as()
        pass

    def save_as(self):
        filename = asksaveasfilename(filetypes=[("sbr","*.sbr")])
        if filename:
            if not self.secureBook.key:
                self.change_key()
            self.secureBook.save(url=filename)
            self.statusLabel.config(text="Saved in %s"% filename)
        pass
    
    def newBook(self):
        self.secureBook = SecureBook("",0,"")
        self.clear()
        pass
    
    def newRecord(self):
        if self.secureBook == None:
            self.newBook()
        if self.secureBook != None:    
            srw = SecureRecordWidget(Toplevel(),None,"",self)
            srw.grid(row=1,column=1)
 
        pass
    
    def delete_record(self):
        iids = self.bookTreeview.selection()   
        message="共%d个记录."%len(iids)
        if askyesnocancel("真的要删除这些记录吗？",message):
            for iid in iids:
                self.secureBook.remove(self.iidRecord[iid])
                self.bookTreeview.delete(iid)   
            self.statusLabel.config(text = "删除%d个记录."% len(iids))         
            
    
    def clear(self):
        for i in self.bookTreeview.get_children():
            self.bookTreeview.delete(i)
        self.iidRecord.clear()

    def sort(self,bytype):
        pass
    
    def sortClear(self):
        pass
    
    def open_command(self):
        self.clear()
        filename = askopenfilename(filetypes=[("sbr","*.sbr")])
        if filename == "":
            return
        self.secureBookName.set(filename)
        trycount = 0
        while trycount<3:
            self.password = askstring("请输入密码","密码")
            if self.openBookwithPassword(self.password,book_type="FILE"):
                break
            showinfo("密码错误","请再次输入密码。三次错误后退出！")
            trycount += 1

    def open_net_command(self):
        self.clear()
        self.userid = askstring("请输入用户名","用户名")
        self.secureBookName.set(self.userid)
        trycount = 0
        while trycount<3:
            self.password = askstring("请输入密码","密码")
            if self.openBookwithPassword(self.password,book_type="NETDISK_189"):
                break
            showinfo("密码错误","请再次输入密码。三次错误后退出！")
            trycount += 1
        pass

    def openBookwithPassword(self,password,book_type):
#         try:
        self.password = password
        self.secureBook = SecureBook(self.secureBookName.get(),book_type=book_type,key=self.password)
        self.secureBook.load()
        for record in self.secureBook.recordlist:
            self.insertItem("", record)
#         except:
#             print(Exception)
#             return False
        return True
    
    def popupCopy(self):
        self.clipboard_clear()
        self.clipboard_append(string=self.folderPath.get(),type='STRING') 
        
    def popupPaste(self):
        self.folderPath.set(self.clipboard_get(type='STRING'))
        
    def removeSelected(self):
        print(self.bookTreeview.selection())
        self.bookTreeview.selection_remove(self.bookTreeview.selection())
        return 

    def updateItem(self,iid,record):
        self.bookTreeview.item(iid, \
                                 values=(record["tag"], \
                                         record["name"], \
                                         record["uri"], \
                                         record["username"], \
                                         record["password"], \
                                         record["ref"],\
                                         record["date"] \
                                         ), \
                                )                

    def insertItem(self,treeParent,secure_record):
        if secure_record == None:
            iid = self.bookTreeview.insert(parent=treeParent, index='end', open=True, \
                                          values=("", "", "", "","",""), \
                                      )
            self.iidRecord[iid] = None
            return iid
        if isinstance(secure_record, SecureRecord):
            iid = self.bookTreeview.insert(parent=treeParent, index='end', \
                                 values=(secure_record.record["tag"], \
                                         secure_record.record["name"], \
                                        secure_record.record["uri"], \
                                         secure_record.record["username"], \
                                         secure_record.record["password"], \
                                         secure_record.record["ref"],\
                                         secure_record.record["date"], \
                                         ), \
                                )
            self.iidRecord[iid] = secure_record
        return iid    
        
    def load_csv(self):
        '''
        csv should in format name,uri,username,password,ref
        the first line should be title
        data begin from 2nd line
        '''
        filename = askopenfilename()
        if filename :
            data = open_workbook(filename)
            sheet = data.sheets()[0]
            fields = sheet.row_values(0)
            for r in range(1,sheet.nrows):
                row = sheet.row_values(r)
                record = {"name":"","uri":"","username":"",\
                          "password":"","ref":"","tag":""}
                for i in range(0,len(fields)):
                    record[fields[i]] = row[i]
                record["date"] = date.today()
                srecord = SecureRecord(record=record)
                self.secureBook.append(record=srecord)
                self.insertItem("", srecord)

        pass        
    
    def export_csv(self):
        filename = asksaveasfilename(filetypes=[("csv","*.csv")])
        if filename :
            csv = Workbook()
            sheet = csv.add_sheet('securebook')
            row,col = 0,0
            for field in SecureRecord.getFields():
                sheet.write(row,col,field)
                col += 1
            row,col = row+1,0
            for iid in self.bookTreeview.selection():
                for field in SecureRecord.getFields():
                    sheet.write(row,col,self.iidRecord[iid].get(field))
                    col += 1
                row,col = row+1,0
            csv.save(filename)
                
                
        
        pass

class Test(unittest.TestCase):


    def testName(self):
        pass


if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()